package com.gitee.apanlh.spring;

import com.gitee.apanlh.exp.InitLoadException;
import com.gitee.apanlh.util.base.ArrayUtils;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.log.Log;
import com.gitee.apanlh.util.reflection.ClassUtils;
import com.gitee.apanlh.util.reflection.ReflectionUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 	HttpServletBean
 * 
 * 	@author Pan
 */
public class ServletBeanUtils extends BeanContextUtils {
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private ServletBeanUtils() {
		//	不允许外部实例
		super();
	}
	
	/**
	 * 	获取所有RequestMapping路径
	 * 	<br>key = 路径名称
	 * 	<br>value = class名称
	 */
	static Map<String, String> requestMappingMap;
	
	/**	
	 * 	获取HttpServletRequest对象
	 * 	
	 * 	@author Pan
	 * 	@return	HttpServletRequest
	 */
	public static HttpServletRequest getHttpRequest() {
		ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
		if (servletRequestAttributes == null) {
			throw new NullPointerException("get httpServletRequest error case: requestAttributes is null");
		}
		return servletRequestAttributes.getRequest();
	}
	
	/**	
	 * 	获取HttpServletResponse对象
	 * 	
	 * 	@author Pan
	 * 	@return HttpServletResponse
	 */
	public static HttpServletResponse getHttpResponse() {
		ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
		if (servletRequestAttributes == null) {
			throw new NullPointerException("get httpServletRequest error case: requestAttributes is null");
		}
		return servletRequestAttributes.getResponse();
	}
	
	/**	
	 * 	获取RequestMappingMap
	 * 	
	 * 	@author Pan
	 * 	@return	Map
	 */
	public static Map<String, String> getRequestMappingMap() {
		return requestMappingMap;
	}
	
	/**
	 * 	扫描Controller获取所有的相关路径
	 * 	@author Pan
	 */
	static void initGetRequestMapping() {
		requestMappingMap = new ConcurrentHashMap<>(16);
		try {
			IteratorUtils.entrySet(getApplicationContext().getBeansWithAnnotation(Controller.class), (className, value, iterator) -> {
				//	某类因为调用了某个方法 会被变成EnhancerBySpringCGLB代理类 需要获取原始类 
				Class<?> clazz = ClassUtils.getProxyClass(value.getClass(), "$$");
				
				//	获取主类的RequestMapping注解
				if (ReflectionUtils.scanClassAnnotation(clazz, Controller.class, RequestMapping.class) 
						|| ReflectionUtils.scanClassAnnotation(clazz, RestController.class, RequestMapping.class)) {
					
					RequestMapping clazzRequestMapping = clazz.getAnnotation(RequestMapping.class);
					String clazzRequestMappingValue = ArrayUtils.toString(clazzRequestMapping.value());
					
					// 方法注解
					for (Method method : ReflectionUtils.getMethodAnnotation(clazz, RequestMapping.class)) {
						RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
						String methodMappingValue = ArrayUtils.toString(methodRequestMapping.value());
						if (methodMappingValue.indexOf('/') == -1) {
							methodMappingValue = "/".concat(methodMappingValue);
						}
						//	类+方法组成的url
						requestMappingMap.put(clazzRequestMappingValue.concat(methodMappingValue), className);
					}
				}
			});
			String json = JsonUtils.toJson(requestMappingMap);
			Log.get().info("init load requestMapping :{}", json);
		} catch (Exception e) {
			throw new InitLoadException(StringUtils.format("init load requestMapping error cause:{}", e.getMessage()), e);
		}
	}

}
